package com.yzf.demo.demo.annotation.ioc;

import com.yzf.demo.demo.annotation.anno.DemoBeanAnnotation;
import com.yzf.demo.demo.annotation.anno.DemoComponentAnnotation;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.HashSet;

/**
 * Created by 于占峰 on 2020/3/28/028.
 */
public class Main {
    //声明用于装入类路径的set集合
    private static HashSet<String> classPathSet = new HashSet<>();

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
        getClassPath("com.yzf.demo.demo.annotation");
        //遍历类名集合
        for (String className : classPathSet) {
            Class<?> clazz = Class.forName(className);
            //判断类是否存在DemoComponentAnnotation注解
            if (clazz.isAnnotationPresent(DemoComponentAnnotation.class))
                //实例化并装入IOC容器
                IOCContainer.putBean(className, clazz.newInstance());
            //获得类的方法列表
            Method[] methods = clazz.getDeclaredMethods();
            //遍历
            for (Method method : methods) {
                //判断method是否存在DemoBean注解
                if (method.isAnnotationPresent(DemoBeanAnnotation.class)) {
                    //获得方法的DemoBeanAnnotation注解的value
                    String beanName = method.getAnnotation(DemoBeanAnnotation.class).value();
                    //判断是否为静态工厂 如果是静态工厂则直接调用方法初始化对象 而不用考虑形参和对象
                    if (Modifier.isStatic(method.getModifiers())) {
                        IOCContainer.putBean(beanName, method.invoke(null));
                    } else {
                        //如果是实例工厂 从容器中取出实例对象 并再次实例化后装入
                        IOCContainer.putBean(beanName, method.invoke(IOCContainer.getBean(className)));
                    }
                }
            }
        }
    }


    private static void getClassPath(String packageStr) {
        //获得本地路径
        URL url = Main.class.getResource("/" + packageStr.replaceAll("\\.", "/"));
        //得到文件对象
        File classDir = new File(url.getFile());
        //遍历
        for (File file : classDir.listFiles()) {
            if (file.isDirectory()) {
                //如果是文件夹则继续向下递归
                getClassPath(packageStr + "." + file.getName());
            } else {
                //判断文件是否为.class结尾的文件 如果不是能跳入下一次循环
                if (!file.getName().endsWith(".class")) continue;
                //替换掉.class后缀 拼接为类的包路径名
                String clazzName = (packageStr + "." + file.getName().replace(".class", ""));
                //装入集合
                classPathSet.add(clazzName);
            }
        }
    }

    ;
}
